import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import com.google.android.maps.GeoPoint;

import android.content.Context;
import android.location.*;
import android.os.Bundle;

public class GeoLocation implements LocationListener {
	private Context thisContext=null;
	private LocationManager manager=null;
	private String bestProvider=null;
	private Location thisLocation=null;
	
	public GeoLocation(Context theContext){
		thisContext = theContext;

		manager = (LocationManager) thisContext.getSystemService(Context.LOCATION_SERVICE);
	    Criteria criteria = new Criteria();
	    bestProvider = manager.getBestProvider(criteria, true);
	    registerForLocationUpdates();
	}
	
	private void registerForLocationUpdates(){
	    manager.requestLocationUpdates(bestProvider, 15000, 1, (LocationListener) this);
	}
	
	public Location getBestCurrentLocation(){
		Location myLocation=null;
	    myLocation = manager.getLastKnownLocation(bestProvider);
	    if (myLocation == null){
	    	myLocation = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
	    }
	    if (myLocation != null){
	    	System.out.println("GeoLocation is >"+myLocation.toString()+"<");
	    	thisLocation = myLocation;
	    }
		return thisLocation;
	}
	
	public String getNameFromLocation(Location aLocation){
		String localityName = null, address = null, returnName=null;
	    HttpURLConnection connection = null;
	    URL serverAddress = null;

	    try {
	        // build the URL using latitude & longitude 
	        // XML return format
	        serverAddress = new URL("http://maps.google.com/maps/geo?q=" + 
	        					     Double.toString(aLocation.getLatitude()) + "," + 
	        					     Double.toString(aLocation.getLongitude()) +
	        					     "&output=xml&oe=utf8&sensor=true&key=" + 
	        					     "0gnB1it3gGRvFkdhjqBahvgiSsVwUKuuNTXuUeA");
	        //Set up initial connection
			connection = (HttpURLConnection)serverAddress.openConnection();
			connection.setRequestMethod("GET");
			connection.setDoOutput(true);
			connection.setReadTimeout(10000);
		                  
			connection.connect();
		    
			try{
				InputStreamReader isr = new InputStreamReader(connection.getInputStream());
				InputSource source = new InputSource(isr);
				SAXParserFactory factory = SAXParserFactory.newInstance();
				SAXParser parser = factory.newSAXParser();
				XMLReader xr = parser.getXMLReader();
				LocationKMLHandler handler = new LocationKMLHandler();
				
				xr.setContentHandler(handler);
				xr.parse(source);
				
				localityName = handler.getLocalityName();
				address = handler.getAddress();
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
			
	    }
	    catch (Exception e){
	        e.printStackTrace();
	    }
	    if((returnName = address)==null) returnName = localityName;
	    return (returnName);
	}
	
	public GeoPoint getGeoPointFromName(String locationName) {
		GeoPoint tempGeoPoint=null;
        String cleanLocationName = locationName.replaceAll(" ","%20");
        
		HttpGet httpGet = new HttpGet(
				"http://maps.google.com/maps/api/geocode/json?address="
				+ cleanLocationName
				+ "&sensor=false");
		HttpClient client = new DefaultHttpClient();
		HttpResponse response;
		StringBuilder stringBuilder = new StringBuilder();

		try {
			response = client.execute(httpGet);
			HttpEntity entity = response.getEntity();
			InputStream stream = entity.getContent();
			int b;
			while ((b = stream.read()) != -1) {
				stringBuilder.append((char) b);
			}


			JSONObject jsonLocation = new JSONObject();
			jsonLocation = new JSONObject(stringBuilder.toString());

			tempGeoPoint = getGeoPointFromJSON(jsonLocation);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tempGeoPoint;	
	}

	public Location getLocationFromName(String locationName) {
		GeoPoint tempGeoPoint=null;
		Location returnLocation = new Location(bestProvider);
		
		tempGeoPoint = this.getGeoPointFromName(locationName);
		double latitude = tempGeoPoint.getLatitudeE6()/1000000;
		double longitude = tempGeoPoint.getLongitudeE6()/1000000;

		returnLocation.setLatitude(latitude);
		returnLocation.setLongitude(longitude);
		return returnLocation;
		
	}

	private static GeoPoint getGeoPointFromJSON(JSONObject jsonObject) {
	    GeoPoint returnGeoPoint=null;
		try {
			Double longitude = new Double(0);
			Double latitude = new Double(0);
			longitude = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
				.getJSONObject("geometry").getJSONObject("location")
				.getDouble("lng");

			latitude = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
				.getJSONObject("geometry").getJSONObject("location")
				.getDouble("lat");
			returnGeoPoint = new GeoPoint((int) (latitude * 1E6), (int) (longitude * 1E6));

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        return returnGeoPoint;
	}

	public void onLocationChanged(Location location) {
		System.out.println("Location changed to >"+location.toString());
		thisLocation = location;
	}
	
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
		
	}
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
		
	}
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
		
	}

}
